package com.zhiwen.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhiwen.common.exception.BusinessException;
import com.zhiwen.domain.dto.RegisterDTO;
import com.zhiwen.domain.dto.UserDTO;
import com.zhiwen.domain.entity.User;
import com.zhiwen.domain.entity.Answer;
import com.zhiwen.domain.entity.Question;
import com.zhiwen.domain.entity.UserFollow;
import com.zhiwen.mapper.UserMapper;
import com.zhiwen.mapper.AnswerMapper;
import com.zhiwen.mapper.QuestionMapper;
import com.zhiwen.mapper.UserFollowMapper;
import com.zhiwen.service.UserService;
import com.zhiwen.domain.vo.UserVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.dev33.satoken.stp.StpUtil;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final BCryptPasswordEncoder passwordEncoder;
    private final UserFollowMapper userFollowMapper;
    private final QuestionMapper questionMapper;
    private final AnswerMapper answerMapper;

    @Override
    public User getByUsername(String username) {
        return getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
    }

    @Override
    public User getByEmail(String email) {
        return getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, email));
    }

    @Override
    public User getByMobile(String mobile) {
        return getOne(new LambdaQueryWrapper<User>().eq(User::getMobile, mobile));
    }

    @Override
    public User getByAccount(String account) {
        return getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, account)
                .or()
                .eq(User::getEmail, account)
                .or()
                .eq(User::getMobile, account));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO register(RegisterDTO registerDTO) {
        // 校验两次密码是否一致
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new BusinessException("两次密码不一致");
        }

        // 校验用户名是否已存在
        if (getByUsername(registerDTO.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }

        // 校验邮箱是否已存在
        if (StrUtil.isNotBlank(registerDTO.getEmail()) && getByEmail(registerDTO.getEmail()) != null) {
            throw new BusinessException("邮箱已被注册");
        }

        // 校验手机号是否已存在
        if (StrUtil.isNotBlank(registerDTO.getMobile()) && getByMobile(registerDTO.getMobile()) != null) {
            throw new BusinessException("手机号已被注册");
        }

        // 创建用户
        User user = new User();
        BeanUtils.copyProperties(registerDTO, user);

        // 设置默认值
        user.setNickname(StrUtil.isBlank(registerDTO.getNickname()) ? registerDTO.getUsername() : registerDTO.getNickname());
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        user.setAvatar("https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png");
        user.setStatus(1);
        user.setRole(1);
        user.setPoints(0);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        // 保存用户
        save(user);

        return getUserVO(user);
    }

    @Override
    public UserVO getUserVO(User user) {
        if (user == null) {
            return null;
        }

        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);

        // 设置关注数
        LambdaQueryWrapper<UserFollow> followingWrapper = new LambdaQueryWrapper<>();
        followingWrapper.eq(UserFollow::getUserId, user.getId());
        followingWrapper.eq(UserFollow::getDeleted, 0);
        Integer followCount = userFollowMapper.selectCount(followingWrapper).intValue();
        userVO.setFollowCount(followCount);

        // 设置粉丝数
        LambdaQueryWrapper<UserFollow> followerWrapper = new LambdaQueryWrapper<>();
        followerWrapper.eq(UserFollow::getFollowUserId, user.getId());
        followerWrapper.eq(UserFollow::getDeleted, 0);
        Integer followerCount = userFollowMapper.selectCount(followerWrapper).intValue();
        userVO.setFollowerCount(followerCount);

        // 设置问题数
        LambdaQueryWrapper<Question> questionWrapper = new LambdaQueryWrapper<>();
        questionWrapper.eq(Question::getUserId, user.getId());
        questionWrapper.eq(Question::getDeleted, 0);
        Integer questionCount = questionMapper.selectCount(questionWrapper).intValue();
        userVO.setQuestionCount(questionCount);

        // 设置回答数
        LambdaQueryWrapper<Answer> answerWrapper = new LambdaQueryWrapper<>();
        answerWrapper.eq(Answer::getUserId, user.getId());
        answerWrapper.eq(Answer::getDeleted, 0);
        Integer answerCount = answerMapper.selectCount(answerWrapper).intValue();
        userVO.setAnswerCount(answerCount);

        // 设置当前用户是否已关注该用户
        userVO.setFollowed(false);
        try {
            if (StpUtil.isLogin()) {
                Long loginUserId = StpUtil.getLoginIdAsLong();
                if (!loginUserId.equals(user.getId())) {
                    LambdaQueryWrapper<UserFollow> followedWrapper = new LambdaQueryWrapper<>();
                    followedWrapper.eq(UserFollow::getUserId, loginUserId);
                    followedWrapper.eq(UserFollow::getFollowUserId, user.getId());
                    followedWrapper.eq(UserFollow::getDeleted, 0);
                    Integer count = userFollowMapper.selectCount(followedWrapper).intValue();
                    userVO.setFollowed(count > 0);
                }
            }
        } catch (Exception e) {
            // 忽略登录检查异常
        }

        return userVO;
    }

    /**
     * 获取用户信息
     *
     * @param id 用户ID
     * @return 用户信息
     */
    @Override
    public UserVO getUserInfo(Long id) {
        User user = this.getById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        return getUserVO(user);
    }

    /**
     * 更新用户信息
     *
     * @param userDTO 用户信息
     * @return 更新后的用户信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserVO updateUserInfo(UserDTO userDTO) {
        User user = this.getById(userDTO.getId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 只允许更新部分字段
        if (StringUtils.hasText(userDTO.getNickname())) {
            user.setNickname(userDTO.getNickname());
        }
        if (StringUtils.hasText(userDTO.getAvatar())) {
            user.setAvatar(userDTO.getAvatar());
        }
        if (StringUtils.hasText(userDTO.getBio())) {
            user.setBio(userDTO.getBio());
        }
        if (userDTO.getGender() != null) {
            user.setGender(userDTO.getGender());
        }

        // 不直接更新敏感信息如邮箱、手机号，这些需要单独的验证接口

        this.updateById(user);
        return getUserVO(user);
    }

    /**
     * 分页获取用户列表
     *
     * @param page 分页对象
     * @param keyword 搜索关键词
     * @return 用户分页列表
     */
    @Override
    public Page<UserVO> getUserPage(Page<User> page, String keyword) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        // 如果有关键字，搜索用户名、昵称或邮箱
        if (StrUtil.isNotBlank(keyword)) {
            wrapper.like(User::getUsername, keyword)
                  .or().like(User::getNickname, keyword)
                  .or().like(User::getEmail, keyword);
        }

        // 按创建时间倒序
        wrapper.orderByDesc(User::getCreateTime);

        // 执行分页查询
        Page<User> userPage = this.page(page, wrapper);

        // 转换为VO对象
        Page<UserVO> userVOPage = new Page<>();
        userVOPage.setCurrent(userPage.getCurrent());
        userVOPage.setSize(userPage.getSize());
        userVOPage.setTotal(userPage.getTotal());
        userVOPage.setRecords(
                userPage.getRecords().stream()
                        .map(this::getUserVO)
                        .toList()
        );

        return userVOPage;
    }

    /**
     * 设置用户状态（禁用/启用）
     *
     * @param userId 用户ID
     * @param status 状态(0-禁用, 1-启用)
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserStatus(Long userId, Integer status) {
        // 检查用户是否存在
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 校验状态值
        if (status != 0 && status != 1) {
            throw new BusinessException("无效的状态值，只能为0(禁用)或1(启用)");
        }

        // 不允许禁用管理员账号
        if (status == 0 && user.getRole() == 3) {
            throw new BusinessException("不能禁用管理员账号");
        }

        // 设置用户状态
        user.setStatus(status);
        user.setUpdateTime(LocalDateTime.now());

        // 更新用户信息
        return this.updateById(user);
    }

    /**
     * 设置用户角色
     *
     * @param userId 用户ID
     * @param role 角色(1-普通用户, 2-专家用户, 3-管理员)
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserRole(Long userId, Integer role) {
        // 检查用户是否存在
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 校验角色值
        if (role < 1 || role > 3) {
            throw new BusinessException("无效的角色值，只能为1(普通用户)、2(专家用户)或3(管理员)");
        }

        // 设置用户角色
        user.setRole(role);
        user.setUpdateTime(LocalDateTime.now());

        // 如果是设置为专家用户，设置isExpert标识
        if (role == 2) {
            // 如果有User对象中有isExpert字段，可以在这里设置
            // user.setIsExpert(true);
        }

        // 更新用户信息
        return this.updateById(user);
    }

    /**
     * 获取用户统计数据（管理员功能）
     *
     * @return 包含各种统计数据的Map
     */
    @Override
    public Map<String, Object> getUserStatistics() {
        Map<String, Object> statistics = new HashMap<>();

        try {
            // 总用户数
            long totalUsers = this.count();
            statistics.put("totalUsers", totalUsers);

            // 活跃用户数 (过去30天内登录过的用户)
            LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);
            LambdaQueryWrapper<User> activeUsersWrapper = new LambdaQueryWrapper<>();
            activeUsersWrapper.gt(User::getLastLoginTime, thirtyDaysAgo);
            long activeUsers = this.count(activeUsersWrapper);
            statistics.put("activeUsers", activeUsers);

            // 今日新增用户
            LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
            LambdaQueryWrapper<User> todayWrapper = new LambdaQueryWrapper<>();
            todayWrapper.ge(User::getCreateTime, today);
            long newUsersToday = this.count(todayWrapper);
            statistics.put("newUsersToday", newUsersToday);

            // 本周新增用户
            LocalDateTime startOfWeek = today.minusDays(today.getDayOfWeek().getValue() - 1);
            LambdaQueryWrapper<User> weekWrapper = new LambdaQueryWrapper<>();
            weekWrapper.ge(User::getCreateTime, startOfWeek);
            long newUsersThisWeek = this.count(weekWrapper);
            statistics.put("newUsersThisWeek", newUsersThisWeek);

            // 本月新增用户
            LocalDateTime startOfMonth = today.withDayOfMonth(1);
            LambdaQueryWrapper<User> monthWrapper = new LambdaQueryWrapper<>();
            monthWrapper.ge(User::getCreateTime, startOfMonth);
            long newUsersThisMonth = this.count(monthWrapper);
            statistics.put("newUsersThisMonth", newUsersThisMonth);

            // 按角色统计用户
            Map<String, Long> usersByRole = new HashMap<>();

            // 普通用户
            LambdaQueryWrapper<User> normalUserWrapper = new LambdaQueryWrapper<>();
            normalUserWrapper.eq(User::getRole, 1);
            long normalUsers = this.count(normalUserWrapper);
            usersByRole.put("normalUsers", normalUsers);

            // 专家用户
            LambdaQueryWrapper<User> expertUserWrapper = new LambdaQueryWrapper<>();
            expertUserWrapper.eq(User::getRole, 2);
            long expertUsers = this.count(expertUserWrapper);
            usersByRole.put("expertUsers", expertUsers);

            // 管理员
            LambdaQueryWrapper<User> adminUserWrapper = new LambdaQueryWrapper<>();
            adminUserWrapper.eq(User::getRole, 3);
            long adminUsers = this.count(adminUserWrapper);
            usersByRole.put("adminUsers", adminUsers);

            statistics.put("usersByRole", usersByRole);

        } catch (Exception e) {
            // 记录异常，返回空统计
            log.error("获取用户统计数据失败", e);
        }

        return statistics;
    }

    /**
     * 批量删除用户（管理员功能，软删除）
     *
     * @param ids 用户ID列表
     * @return 成功删除的数量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchDeleteUsers(Long[] ids) {
        if (ids == null || ids.length == 0) {
            return 0;
        }

        int count = 0;

        for (Long id : ids) {
            try {
                // 检查用户是否存在
                User user = this.getById(id);
                if (user == null) {
                    continue;
                }

                // 不允许删除管理员账号
                if (user.getRole() == 3) {
                    log.warn("尝试删除管理员账号: {}", id);
                    continue;
                }

                // 执行软删除
                if (this.removeById(id)) {
                    count++;
                }
            } catch (Exception e) {
                log.error("删除用户失败: {}", id, e);
                // 继续处理下一个ID
            }
        }

        return count;
    }

    @Override
    public Map<Long, UserVO> getUserVOMap(List<Long> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return new HashMap<>();
        }

        // 查询用户信息
        List<User> users = listByIds(userIds);

        // 转换为Map
        Map<Long, UserVO> userMap = new HashMap<>();
        for (User user : users) {
            userMap.put(user.getId(), getUserVO(user));
        }

        return userMap;
    }
}
